﻿using Quartz.Impl.Matchers;
using Quartz.Impl.Triggers;
using Quartz;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DynamicQuartz.Schedule.Core
{
    public class QuartzService
    {
        public ISchedulerFactory schedulerFactory;

        public QuartzService(ISchedulerFactory schedulerFactory)
        {
            this.schedulerFactory = schedulerFactory;
        }


        public async Task<List<JobDetail>> GetAllJobs()
        {
            var scheduler = await schedulerFactory.GetScheduler();

            List<JobKey> jobKeyList = new List<JobKey>();
            List<JobDetail> jobDetailList = new List<JobDetail>();
            var groupNames = await scheduler.GetJobGroupNames();
            foreach (var groupName in groupNames.OrderBy(t => t))
            {
                jobKeyList.AddRange(await scheduler.GetJobKeys(GroupMatcher<JobKey>.GroupEquals(groupName)));
            }
            foreach (var jobKey in jobKeyList.OrderBy(t => t.Name))
            {
                var jobDetail = await scheduler.GetJobDetail(jobKey);
                if (jobDetail == null)
                    continue;
                var triggersList = await scheduler.GetTriggersOfJob(jobKey);
                var triggers = triggersList.AsEnumerable().FirstOrDefault();
                if (triggers == null)
                    continue;

                var interval = string.Empty;
                if (triggers is SimpleTriggerImpl)
                    interval = (triggers as SimpleTriggerImpl)?.RepeatInterval.ToString();
                else
                    interval = (triggers as CronTriggerImpl)?.CronExpressionString;

                jobDetailList.Add(new JobDetail()
                {
                    JobGroupName = jobKey.Group ?? "",
                    JobName = jobKey.Name ?? "",
                    TriggerState = await scheduler.GetTriggerState(triggers.Key),
                    PreviousFireTime = triggers.GetPreviousFireTimeUtc()?.LocalDateTime,
                    NextFireTime = triggers.GetNextFireTimeUtc()?.LocalDateTime,
                    StartTime = triggers.StartTimeUtc.LocalDateTime,
                    EndTime = triggers.EndTimeUtc?.LocalDateTime,
                    JobDescription = jobDetail.Description ?? "",
                    ScheduleExpression = interval ?? "",
                    ScheduleExpressionDescription = triggers.Description ?? "",
                    JobData = JsonConvert.SerializeObject(jobDetail.JobDataMap)

                });
            }
            return jobDetailList;
        }

        /// <summary>
        /// 立即执行一个作业（Job）
        /// </summary>
        /// <param name="jobKey"></param>
        /// <returns></returns>
        public async Task<ResultBaseDto> ImmediatelyExecuteJob(JobKey jobKey)
        {
            ResultBaseDto resultBaseDto = new ResultBaseDto();
            var scheduler = await schedulerFactory.GetScheduler();

            try
            {
                await scheduler.TriggerJob(jobKey);
                resultBaseDto.Success = true;
            }
            catch (Exception ex)
            {
                resultBaseDto.Success = false;
                resultBaseDto.FailedMsg = ex.Message;
            }
            return resultBaseDto;
        }

        /// <summary>
        /// 要恢复（Resume）一个暂停的作业（Job）
        /// </summary>
        /// <param name="jobKey"></param>
        /// <returns></returns>
        public async Task<ResultBaseDto> ResumeJob(JobKey jobKey)
        {
            var scheduler = await schedulerFactory.GetScheduler();
            ResultBaseDto resultBaseDto = new ResultBaseDto();
            if (await scheduler.CheckExists(jobKey))//检查job是否存在
            {
                try
                {
                    await scheduler.ResumeJob(jobKey);
                    resultBaseDto.Success = true;

                }
                catch (Exception ex)
                {
                    resultBaseDto.Success = false;
                    resultBaseDto.FailedMsg = ex.Message;
                }
            }
            else
            {
                resultBaseDto.Success = false;
                resultBaseDto.FailedMsg = "该Job已经不存在";
            }

            return resultBaseDto;
        }


        /// <summary>
        /// 暂停作业（Job）
        /// </summary>
        /// <param name="jobKey"></param>
        /// <returns></returns>
        public async Task<ResultBaseDto> SuspendJob(JobKey jobKey)
        {
            ResultBaseDto resultBaseDto = new ResultBaseDto();
            var scheduler = await schedulerFactory.GetScheduler();

            try
            {
                await scheduler.PauseJob(jobKey);
                resultBaseDto.Success = true;
            }
            catch (Exception ex)
            {
                resultBaseDto.Success = false;
                resultBaseDto.FailedMsg = ex.Message;
            }
            return resultBaseDto;
        }
    }
}
